import React, {FC, useLayoutEffect, useRef} from 'react';

import * as PDFJS from 'pdfjs-dist'
// @ts-ignore
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'
import {PDFDocumentProxy} from "pdfjs-dist/types/display/api";


PDFJS.GlobalWorkerOptions.workerSrc = pdfjsWorker

export interface PdfViewerProps {
    /**
     * 是否允许携带凭证(cookie).默认:false
     */
    withCredentials?: boolean;
    /**
     * pdf文件地址
     */
    pdfUrl: string | null;
    /**
     * cMap的url地址(用于解决中文乱码或中文显示为空白的问题). 该资源的物理路径在: node_modules/pdfjs-dist/cmaps
     */
    cMapUrl: string;
    /**
     * 自定义请求头
     */
    httpHeaders?: object;
    /**
     * pdf缩放比. 默认:1.5
     */
    scale?: number;
}

/**
 * 渲染pdf文件的指定页到画板
 * @param pdfViewerDom 承载pdf画板的dom容器
 * @param pdfDoc pdf文件
 * @param pageNum 需要渲染的页码
 * @param scale 缩放比例
 */
export function renderPdfOnePage(pdfViewerDom: HTMLDivElement, pdfDoc: PDFDocumentProxy, pageNum: number, scale: number) {
    // 创建画布
    const canvas = document.createElement('canvas');
    pdfViewerDom.appendChild(canvas);
    // 获取2d上下文
    const context = canvas.getContext('2d');
    pdfDoc.getPage(pageNum).then((page) => {
        // 获取当前pdf页内容, 并设置缩放
        const viewport = page.getViewport({scale: scale});
        // @ts-ignore
        const realCanvas = context.canvas;
        realCanvas.width = viewport.width;
        realCanvas.height = viewport.height;
        // 将pdf当前页内容画到2d画板中
        // @ts-ignore
        page.render({canvasContext: context, viewport})
    })
}

/**
 * 完整显示pdf内容
 * @param props
 * @constructor
 */
const PdfViewer: FC<PdfViewerProps> = (props) => {
    const {pdfUrl, scale, cMapUrl, httpHeaders, withCredentials} = props;
    // 存放pdf文档
    const pdfDocRef = useRef<PDFDocumentProxy | null>(null);
    // 存放承载pdf画布的dom容器
    const pdfViewerRef = useRef<HTMLDivElement>(null);

    /**
     * 渲染pdf的画布
     * @param pdfViewerDom 承载pdf画布的dom容器
     * @param pdfDoc pdf文档
     * @param scale 缩放比例
     */
    function renderPdfCanvas(pdfViewerDom: HTMLDivElement, pdfDoc: PDFDocumentProxy, scale: number) {
        // 清除原来的pdf画布
        pdfViewerDom.innerHTML = '';
        // 获取总页数
        const totalPage = pdfDoc.numPages;
        // 获取显示容器
        for (let i = 1; i <= totalPage; i++) {
            // 循环处理pdf的每页
            renderPdfOnePage(pdfViewerDom, pdfDoc, i, scale);
        }
    }

    useLayoutEffect(() => {
        if (pdfUrl) {
            // 获取pdf文件
            const pdfLoadingTask = PDFJS.getDocument({
                url: pdfUrl,
                withCredentials: withCredentials, // 携带凭证
                httpHeaders,
                cMapUrl,
                cMapPacked: true
            });
            pdfLoadingTask.promise.then((pdfDoc) => {
                const pdfViewerDom = pdfViewerRef.current;
                if (pdfDoc && pdfViewerDom) {
                    // 缓存pdf内容
                    pdfDocRef.current = pdfDoc;
                    // @ts-ignore
                    renderPdfCanvas(pdfViewerDom, pdfDoc, scale);
                }
            })
        }
    }, [pdfUrl, cMapUrl]);

    useLayoutEffect(() => {
        const pdfDoc = pdfDocRef.current;
        const pdfViewerDom = pdfViewerRef.current;
        if (pdfDoc && pdfViewerDom) {
            // @ts-ignore
            renderPdfCanvas(pdfViewerDom, pdfDoc, scale);
        }
    }, [scale])

    return (
        <div ref={pdfViewerRef}>

        </div>
    );
};

PdfViewer.defaultProps = {
    /**
     * pdf默认缩放比:1.5
     */
    scale: 1.5,
    httpHeaders: {},
    withCredentials: false
}

export default PdfViewer;


